package io.coderyeah.ymcc.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.kernel.Config;
import com.alipay.easysdk.payment.page.models.AlipayTradePagePayResponse;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import io.coderyeah.ymcc.domain.AlipayInfo;
import io.coderyeah.ymcc.domain.CourseOrder;
import io.coderyeah.ymcc.domain.PayFlow;
import io.coderyeah.ymcc.domain.PayOrder;
import io.coderyeah.ymcc.dto.AlipayNotifyDto;
import io.coderyeah.ymcc.dto.PayDTO;
import io.coderyeah.ymcc.dto.PayResultMsgInMQ;
import io.coderyeah.ymcc.service.IAlipayInfoService;
import io.coderyeah.ymcc.service.IPayFlowService;
import io.coderyeah.ymcc.service.IPayOrderService;
import io.coderyeah.ymcc.service.IPayService;
import io.coderyeah.ymcc.util.AssertUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.producer.SendStatus;
import org.apache.rocketmq.client.producer.TransactionSendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * @author lqs
 * @date 2022/11/4 16:47
 */
@Slf4j
@Service
public class PayServiceImpl implements IPayService {
    @Autowired
    private IPayOrderService payOrderService;
    @Autowired
    private IAlipayInfoService alipayInfoService;
    @Autowired
    private IPayFlowService flowService;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Override
    public String apply(PayDTO payDTO) {
        // 根据订单号查寻订单
        PayOrder order = payOrderService.getByOrderSn(payDTO.getOrderNo());
        AssertUtil.isNotNull(order, "支付订单不存在");
        // 判断订单是否支付
        AssertUtil.isEqualsTrim(order.getPayStatus().toString(), CourseOrder.TO_BE_PAID.toString(), "订单已处理");
        // 查询alipay信息
        AlipayInfo alipayInfo = alipayInfoService.selectById(2L);

        // 回调地址
        String returnUrl = payDTO.getCallUrl() != null ? payDTO.getCallUrl() : alipayInfo.getReturnUrl();

        // 调用支付宝接口完成支付
        // 1. 设置参数（全局只需设置一次）
        Factory.setOptions(getOptions(alipayInfo));
        try {
            AlipayTradePagePayResponse response = Factory.Payment.Page().pay(
                    order.getSubject(), payDTO.getOrderNo(), order.getAmount().toString(), alipayInfo.getReturnUrl()
            );
            order.setPayStatus(1);//设置为支付中
            order.setUpdateTime(new Date());
            payOrderService.updateById(order);
            // 将返回的form表单字符串返回前端
            return response.getBody();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public String notify(AlipayNotifyDto notifyDto) {
        Map map = JSON.parseObject(JSON.toJSONString(notifyDto), Map.class);
        Boolean aBoolean;
        try {
            // 验证签名
            aBoolean = Factory.Payment.Common().verifyNotify(map);
            if (!aBoolean) return "fail";
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 验证支付状态 根据订单号查询数据库确认订单是否未处理
        PayOrder o = payOrderService.getByOrderSn(notifyDto.getOut_trade_no());
        // 1-支付中 0-待支付
        if (o == null || !Objects.equals(o.getPayStatus(), PayOrder.PAYING)) {
            return "fail";
        }


        //发起支付宝的退款
        if (o.getPayStatus().equals(PayOrder.PAY_TIMEOUT)){
            try {
                Factory.Payment.Common().refund(notifyDto.getOut_trade_no(),notifyDto.getTotal_amount());
            } catch (Exception e) {
                e.printStackTrace();
                log.info("支付宝退款失败：{}",e.getMessage());
            }
        }


        if (notifyDto.getTrade_status().equals(AlipayNotifyDto.TRADE_SUCCESS)
                || notifyDto.getTrade_status().equals(AlipayNotifyDto.TRADE_FINISHED)) {
            Date date = new Date();
            // 更改支付订单状态
            o.setPayStatus(PayOrder.PAY_SUCCESS);//支付完成
            o.setUpdateTime(date);
//            payOrderService.updateById(o);
            // 生成支付流水
            PayFlow payFlow = new PayFlow();
            payFlow.setNotifyTime(date);
            payFlow.setPaySuccess(true);
            payFlow.setSubject(o.getSubject());
            payFlow.setOutTradeNo(notifyDto.getOut_trade_no());
            payFlow.setTotalAmount(new BigDecimal(notifyDto.getTotal_amount()));
            payFlow.setTradeStatus(notifyDto.getTrade_status());
            payFlow.setPassbackParams(notifyDto.getPassback_params());
//            flowService.insert(payFlow);

            // 发送事务消息 订单和课程服务需要消费此此消息
            HashMap<String, Object> orderMap = new HashMap<>();
            orderMap.put("payOrder", o);
            orderMap.put("payFlow", payFlow);
            // 封装事务消息
            PayResultMsgInMQ msg = new PayResultMsgInMQ(o.getOrderNo(), o.getExtParams());

            Message<PayResultMsgInMQ> message = MessageBuilder.withPayload(msg).build();
            TransactionSendResult result = rocketMQTemplate.sendMessageInTransaction("tx-payresult-producer",
                    "payresult-topic:payresult-tags", message, orderMap);
            log.info("事务消息发送成功。。。。。。。。。。。");
            if (!result.getSendStatus().equals(SendStatus.SEND_OK)) {
                // 消息发送失败
                return "fail";
            }
        }
        return "success";
    }


    private Config getOptions(AlipayInfo alipayInfo) {
        Config config = new Config();
        config.protocol = alipayInfo.getProtocol();
        config.gatewayHost = alipayInfo.getGatewayHost();
        config.signType = alipayInfo.getSignType();
        config.appId = alipayInfo.getAppId();
        // 为避免私钥随源码泄露，推荐从文件中读取私钥字符串而不是写入源码中
        config.merchantPrivateKey = alipayInfo.getMerchantPrivateKey();
        config.alipayPublicKey = alipayInfo.getAlipayPublicKey();
        //可设置异步通知接收服务地址（可选）
        config.notifyUrl = alipayInfo.getNotifyUrl();
        //可设置AES密钥，调用AES加解密相关接口时需要（可选）
        config.encryptKey = "aa4BtZ4tspm2wnXLb1ThQA==";
        return config;
    }
}
